package tool

import java.io.File

import command.CommandExec
import dao._
import org.joda.time.DateTime
import models.Tables._
import implicits.Implicits._
import play.api.mvc.{AnyContent, Request, RequestHeader}
import shared.Pojo._
import upickle.default._

/** Created by Administrator on 2019/8/7
  */
object Pojo {

  case class ChangePasswordData(password: String, newPassword: String)

  sealed trait MissionManager

  case class MissionWrap(mission: MissionRow) extends MissionManager

  case class MissionIdFileData(userId: Int, kind: String, missionId: Int)

  case class WorkflowMissionWrap(mission: WorkflowMissionRow) extends MissionManager

  case object Ask extends MissionManager

  sealed trait MissionAction

  case object RunAction extends MissionAction

  case object Stop extends MissionAction

  case class MyDao(
      missionDao: MissionDao,
      modeDao: ModeDao,
      hmdbKeggInfoDao: HmdbKeggInfoDao,
      hmdbOtherNameKeggDao: HmdbOtherNameKeggDao,
      workflowMissionDao: WorkflowMissionDao,
      matrixFileDataDao: MatrixFileDataDao,
      keggInfoDao: KeggInfoDao
  )

  case class MissionDirData(workspaceDir: File, resultDir: File, logFile: File)

  case class UserData(name: String, password: String)

  case class UnitData(unit: String)

  case class NewPasswordData(phone: String, password: String)

  case class PhoneData(phone: String)

  case class NewPhoneData(newPhone: String)

  case class ConfigNameData(configName: String)

  case class IdOpData(id: Option[Int])

  case class MissionIdData(missionId: Int)

  case class ColumnNameData(columnName: String)

  case class NaIdentifyColorData(naColors: List[String])

  object NaIdentifyColorData {
    implicit val rw = macroRW[NaIdentifyColorData]
  }

  case class SiteNamesData(siteNames: Seq[String])

  case class ColumnNamesData(columnNames: Seq[String])

  case class SexData(sex: String)

  case class ConfigFormData(missionName: String, configName: String)

  case class CommandData(workspace: File, commands: List[String], runFileName: String = "run.sh")

  case class SearchData(
      missionName: Option[String],
      missionIntro: Option[String],
      startDate: Option[DateTime],
      endDate: Option[DateTime]
  )

  case class SampleSearchData(
      id: String,
      indexId: String,
      sampleIntro: String,
      gender: String,
      kind: String,
      comment: String,
      updateMission: String,
      startDate: Option[DateTime],
      endDate: Option[DateTime]
  )

  case class MissionNameCheckData(missionName: String, kind: String)

  object CommandData {

    def empty: CommandData = {
      val workspace: File = new File("")
      val commands: List[String] = List[String]()
      CommandData(workspace, commands)
    }

    def apply(workspace: File, command: String): CommandData = {
      new CommandData(workspace, List(command))
    }

  }

  case class MyData(
      availableDepth: String,
      totalDepth: String,
      interlocusBalance: String,
      singleSource: String,
      iSNPLociTyped: String,
      autosomalLociTyped: String,
      xLociTyped: String,
      yLociTyped: String,
      strAvg: String,
      snpAvg: String,
      strSTD: String,
      snpSTD: String,
      strDepthBelow30: String,
      strDepthBelow100: String
  )

  case class IndexData(index: String, compoundName: String)

  case class MissionData(missionName: String, lane: String, id: String, gender: String, kind: String)

  case class Long2fatData(missionName: String, inputKind: String, fileContent: String)

  trait AddData {
    val inputKind: String
    val fileContent: String
  }

  case class MetDataAddData(
      inputKind: String,
      fileContent: String,
      varUniq: Option[String],
      tags: String,
      comment: String
  ) extends AddData

  case class GroupDataAddData(
      inputKind: String,
      fileContent: String,
      sampleHeader: Option[String],
      classNoteHeader: Option[String],
      pairHeader: Option[String],
      tags: String,
      comment: String
  ) extends AddData

  case class LibDataAddData(
      inputKind: String,
      fileContent: String,
      classHeader: Option[String],
      hmdbHeader: Option[String],
      keggHeader: Option[String],
      metaboliteHeader: Option[String],
      tags: String,
      comment: String
  ) extends AddData

  case class ExchangeData(sampleHeader: String, classNoteHeader: String, pairHeader: Option[String])

  case class NewGroupData(fileName: String, isPaired: Boolean, groupNames: List[String], sampleNames: List[String])

  case class SubData(id: Int, fileName: String, rows: List[String], cols: List[String])

  case class HJoinData(missionName: String, inputKinds: Seq[String], fileContent: Seq[String])

  case class CompareMissionData(userId: Int, missionName: String, sample1: String, sample2: String)

  case class PageData(
      limit: Int,
      offset: Int,
      order: String,
      search: Option[String],
      sort: Option[String],
      gender: Option[List[String]],
      kind: Option[List[String]],
      panel: Option[List[String]],
      id: Option[String],
      indexId: Option[String],
      sampleIntro: Option[String],
      comment: Option[String],
      updateMission: Option[List[String]],
      startTime: Option[DateTime],
      endTime: Option[DateTime],
      containerName: Option[List[String]],
      singleSource: Option[List[String]],
      autosomalLociTyped: Option[List[String]],
      yLociTyped: Option[List[String]],
      xLociTyped: Option[List[String]],
      isnpLociTyped: Option[List[String]],
      interlocusBalance: Option[List[String]]
  )

  case class KitNameData(kitName: String)

  case class MissionNameData(missionName: String)

  case class IdData(id: Int)

  case class IdStrData(idStr: String)

  case class IdStrOpData(idStr: Option[String])

  case class IdsData(ids: List[Int])

  case class IdStrsData(idStrs: List[String])

  case class ExampleData(kind: String, fileName: String)

  case class StepData(missionName: String, stepNum: Int, id: String, kitName: String)

  case class BatchMissionData(
      missionIntro: String,
      dataType: String,
      splitDir: String,
      serverGzFile: String,
      isCover: Option[Boolean]
  )

  case class ServerDirData(splitDir: String)

  case class SampleIdData(id: String)

  case class SampleSummaryData(id: String, panel: String)

  case class KindData(kind: String)

  case class ExtraDataData(prefix: String)

  case class SoftKindData(softKind: String)

  case class SoftKindOpData(softKind: Option[String])

  case class KindOpData(kind: Option[String])

  case class SampleIdsData(ids: Seq[String])

  case class SampleInfoFileCheckData(dbIds: List[String], isCover: Option[Boolean])

  case class GenotypeData(locus: String, genoType: String, qc: String)

  case class StrData(strSiteNames: Seq[String], strSiteDatas: Seq[String])

  case class SnpData(snpSiteNames: Seq[String], snpSiteDatas: Seq[String])

  case class MyFileData(fileName: String, tags: String, comment: String, size: Long)

  object MyFileData {
    implicit val rw = macroRW[MyFileData]
  }

  case class MyFileInfoData(fileName: String, intro: String, kind: String, soft: String)

  object MyFileInfoData {
    implicit val rw = macroRW[MyFileInfoData]
  }

  trait ConfigFileT extends MyDir {
    val configFile: File
  }

  case class MyInputFile(
      rawDataFile: File,
      dataFile: File,
      groupFile: File,
      sampleColorFile: File,
      compareFile: File,
      corDir: File,
      confounderFile: File,
      metaColorFile: File,
      configFile: File,
      solutionFile: Option[File]
  ) extends MyDir
      with ConfigFileT

  case class MyInInput(
      groupFile: File,
      sampleColorFile: File,
      configFile: File,
      corDir: File,
      confounderFile: File,
      dataFile: File,
      metaColorFile: File,
      scaleDataFile: File,
      mustScaleFile: File
  ) extends MyDir
      with mustScaleFileT

  trait InDirTreatT extends MyDir {
    val inDirTreat: InDirTreat
  }

  trait mustScaleFileT extends MyDir {
    val mustScaleFile: File
  }

  trait InDirTreatCs extends MyDir {
    val csDir: File
  }

  trait InDirTreatSms extends MyDir {
    val smsDir: File
  }

  case class InDirTreat(csDir: File, smsDir: File) extends InDirTreatCs with InDirTreatSms

  case class MyDataDir(tmpDir: File, fqFile: File)

  case class MyBatchDataDir(tmpDir: File, gzFile: File, indexFile: File)

  case class DataFileInfo(sampleIds: List[String])

  case class UserNameData(name: String)

  case class EmailData(email: String)

  case class RegisterUserData(
      fullName: String,
      password: String,
      email: String,
      phone: String,
      company: String,
      province: String,
      city: String,
      teacherName: String
  )

  case class UpdateUserData(
      fullName: String,
      email: String,
      phone: String,
      institution: String,
      province: String,
      city: String,
      teacher: String
  )

  case class AdminSetData(gzPath: String)

  case class NodeData(id: String)

  case class ValidCodeData(phone: String, validCode: String)

  case class ValidEmailCodeData(email: String, validCode: String)

  case class Info(subject: String, content: String)

  case class FileNameData(fileName: String)

  object FileNameData {
    implicit val rw = macroRW[FileNameData]
  }

  case class UpdateData(fileName: String, tags: String, comment: String)

  case class FileNamesData(fileNames: List[String])

  case class NameData(name: String)

  case class FileNameOpData(fileName: Option[String])

  case class ColumnNumLeastOpData(columnNumLeast: Option[Int])

  case class OriginalFileNameOpData(originalFileName: Option[String])

  case class OriginalFileNameData(originalFileName: String)

  case class GroupNumOpData(groupNum: Option[Int])

  case class GroupKindData(groupKind: String)

  case class OnlyInterData(onlyInter: Boolean)

  trait InDir {
    val dir01: File = new File(".")
    val dir02: File = new File(".")
    val dir03: File = new File(".")
    val dir04: File = new File(".")
    val inDir04: InDir = null
    val dir05: File = new File(".")

  }

  trait MyDir

  trait rocDir extends MyDir {
    val rocDir: File
  }

  case class InDirMg(gbDir: File, lrDir: File, rfDIr: File, rocDir: File) extends MyDir with rocDir

  case class InDirDignose(rfDir: File, svmDir: File, borutaDir: File, mgDir: File, inDirMg: InDirMg)

  case class MyInDir04(
      override val dir01: File,
      override val dir02: File,
      override val dir03: File,
      override val dir04: File,
      override val inDir04: InDir
  ) extends InDir

  case class MyMessage(valid: Boolean, message: String)

  case class GroupFileInfo(metGroupMap: Map[String, String], pairIdMap: Map[String, String])

  case class CompareFileInfo(map: Map[List[String], Boolean])

  case class FileInfo(groupFileInfo: GroupFileInfo, dataFileInfo: DataFileInfo, compareFileInfo: CompareFileInfo)

  trait MyStep {
    val order: Int
  }

  case object StepBasic extends MyStep {
    override val order: Int = 1
  }

  case object StepPca extends MyStep {
    override val order: Int = 2
  }

  case object Step0 extends MyStep {
    override val order: Int = 0
  }

  case object StepPlsda extends MyStep {
    override val order: Int = 3
  }

  case class StepOplsda(isTest: Boolean = false) extends MyStep {
    override val order = 4
  }

  case class StepUni(isTest: Boolean = false) extends MyStep {
    override val order: Int = 5
  }

  case class StepPotential(isTest: Boolean = false) extends MyStep {
    override val order: Int = 6
  }

  case object StepCor extends MyStep {
    override val order: Int = 7
  }

  case class StepPathway(isTest: Boolean = false) extends MyStep {
    override val order: Int = 8
  }

  case object StepDignose extends MyStep {
    override val order: Int = 9
  }

  trait MyConfig {}

  case class DiffMethodData(
      method: String,
      fcMethod: String,
      mulMethod: String,
      pValue: String,
      fdr: String,
      log2FC: String,
      kwP: String,
      kwFdr: String
  ) extends AnalysisArg

  case class PathwayData(
      isIPathExec: String,
      isEnrichExec: String,
      libTypes: Seq[String],
      isPathwayExec: String,
      method: String,
      nodeImp: String
  ) extends AnalysisArg

  case class CorData(isCorExec: String, isParCorExec: String, coe: String, p: String, fdr: String) extends AnalysisArg

  case class ReportHomeData(
      isTargetTest: String,
      client: Option[String],
      affiliation: Option[String],
      email: Option[String],
      projectCode: Option[String],
      salesRep: Option[String],
      testOrderName: Option[String],
      testOrderId: Option[String],
      sampleType: Option[String]
  ) extends MyConfig

  case class PreDealData(
      missionName: String,
      file: String,
      coef: String,
      replaceMethod: String,
      knn: String,
      min: String,
      isNormal: String
  ) extends AnalysisArg

  object PreDealData {
    implicit val rw = macroRW[PreDealData]
  }

  case class AnnoData(missionName: String, file: String) extends SharedAnnoDataT with AnalysisArg

  object AnnoData {
    implicit val rw = macroRW[AnnoData]
  }

  case class ZScoreData(missionName: String, file: String) extends SharedZScoreDataT with AnalysisArg

  case class IPathData(missionName: String, file: String, hasGroup: Option[String], groupFile: String, fcMethod: String)
      extends SharedIPathDataT
      with AnalysisArg

  object IPathData {
    implicit val rw = macroRW[IPathData]
  }

  case class EnrichData(missionName: String, file: String, libType: String) extends SharedEnrichDataT with AnalysisArg

  object EnrichData {
    implicit val rw = macroRW[EnrichData]
  }

  case class MetMicCorData(
      missionName: String,
      file: String,
      micFile: String,
      hasCov: Option[String],
      covFile: String,
      metaNor: String,
      rarefaction: String,
      r: String,
      alpha: String,
      coe: String,
      p: String
  ) extends AnalysisArg

  case class DiagnoseData(
      missionName: String,
      file: String,
      groupFile: String,
      scaleMethod: String,
      group: String,
      method: String
  ) extends DiagnoseDataT
      with AnalysisArg

  object DiagnoseData {
    implicit val rw = macroRW[DiagnoseData]
  }

  case class PcaData(
      missionName: String,
      file: String,
      hasGroup: Boolean,
      groupFile: String,
      scaleMethod: String,
      isPaired: Boolean
  ) extends SharedPcaDataT
      with AnalysisArg

  object PcaData {
    implicit val rw = macroRW[PcaData]
  }

  case class DiffAnaData(
      missionName: String,
      file: String,
      groupFile: String,
      group: String,
      isPaired: Boolean,
      method: String,
      fcMethod: String,
      pValue: String,
      useFdr: Boolean,
      fdr: String,
      log2FC: String
  ) extends SharedDiffAnaDataT
      with AnalysisArg

  object DiffAnaData {
    implicit val rw = macroRW[DiffAnaData]
  }

  case class LefseAnaData(
      missionName: String,
      file: String,
      groupFile: String,
      level: String,
      a: String,
      w: String,
      l: String,
      y: String
  ) extends SharedLefseAnaDataT
      with AnalysisArg

  object LefseAnaData {
    implicit val rw = macroRW[LefseAnaData]
  }

  case class LimmaAnaData(
      missionName: String,
      file: String,
      groupFile: String,
      groups: List[String],
      covs: List[String],
      kinds: List[String],
      fillMethod: String,
      knn: String
  ) extends SharedLimmaAnaDataT
      with AnalysisArg

  object LimmaAnaData {
    implicit val rw = macroRW[LimmaAnaData]
  }

  case class DiffAnaMulData(
      missionName: String,
      file: String,
      groupFile: String,
      method: String,
      pValue: String,
      useFdr: Boolean,
      fdr: String
  ) extends AnalysisArg

  object DiffAnaMulData {
    implicit val rw = macroRW[DiffAnaMulData]
  }

  case class CcaRdaData(
      missionName: String,
      file: String,
      listFile: String,
      analysisKind: String,
      hasGroup: Option[String],
      groupFile: String
  ) extends AnalysisArg

  case class ParCorData(
      missionName: String,
      file: String,
      hasExtraDataFile: Boolean,
      extraFile: String,
      hasConfounderFile: Boolean,
      confounderFile: String,
      corMethod: String,
      fdrMethod: String,
      coe: String,
      p: String,
      fdr: String
  ) extends SharedParCorDataT
      with AnalysisArg

  object ParCorData {
    implicit val rw = macroRW[ParCorData]
  }

  case class HeatmapData(
      missionName: String,
      file: String,
      hasRowGroup: Boolean,
      rowGroupFile: String,
      selectColumns: List[String],
      hasColGroup: Boolean,
      colGroupFile: String
  ) extends SharedHeatmapDataT
      with AnalysisArg

  object HeatmapData {
    implicit val rw = macroRW[HeatmapData]
  }

  case class PlsdaData(missionName: String, file: String, groupFile: String, scaleMethod: String, isPaired: Boolean)
      extends PlsdaDataT
      with AnalysisArg

  object PlsdaData {
    implicit val rw = macroRW[PlsdaData]
  }

  case class IsPairedData(file: String, groupFile: String) extends AnalysisArg

  case class GroupData(group: String)

  case class BorutaData(
      missionName: String,
      file: String,
      groupFile: String,
      scaleMethod: String,
      maxRuns: String,
      pValue: String
  ) extends SharedBorutaDataT
      with AnalysisArg

  object BorutaData {
    implicit val rw = macroRW[BorutaData]
  }

  case class RfData(
      missionName: String,
      file: String,
      groupFile: String,
      scaleMethod: String,
      ntree: String,
      hasMtry: Boolean,
      mtry: String,
      replace: String,
      hasNodesize: Boolean,
      nodesize: String,
      hasMaxnodes: Boolean,
      maxnodes: String,
      topM: String
  ) extends SharedRfDataT
      with AnalysisArg

  object RfData {
    implicit val rw = macroRW[RfData]
  }

  case class SvmData(
      missionName: String,
      file: String,
      groupFile: String,
      scaleMethod: String,
      kernel: String,
      cost: String,
      tolerance: String,
      epsilon: String,
      gamma: String,
      coef0: String,
      degree: String,
      topM: String
  ) extends SharedSvmDataT
      with AnalysisArg

  object SvmData {
    implicit val rw = macroRW[SvmData]
  }

  case class BiomarkerData(missionName: String, file: String, diffFiles: List[String], isInter: String)
      extends AnalysisArg

  case class VennData(missionName: String, labels: List[String], diffFiles: List[String]) extends AnalysisArg

  case class BasicData(
      missionName: String,
      file: String,
      groupFile: String,
      isPaired: Option[String],
      method: String,
      fcMethod: String,
      mulMethod: String
  ) extends SharedBasicDataT
      with AnalysisArg

  object BasicData {
    implicit val rw = macroRW[BasicData]
  }

  case class OplsdaData(
      missionName: String,
      file: String,
      groupFile: String,
      scaleMethod: String,
      group: String,
      vip: String,
      q2Y: String,
      q2YB: String
  ) extends OplsdaDataT
      with AnalysisArg

  object OplsdaData {
    implicit val rw = macroRW[OplsdaData]
  }

  case class DetailData(fileName: String, kind: String)

  case class ConfigData(
      threadNum: Int,
      isInter: String,
      rfTop: String,
      svmTop: String,
      cor: CorData,
      pathway: PathwayData,
      species: String,
      isSmp: String,
      anaKind: String,
      diagnoseIsExec: String,
      coef: String,
      isLoess: String,
      isNormal: String,
      preDeal: PreDealData,
      diffMethod: DiffMethodData,
      oplsda: OplsdaData,
      borutaIsInter: String,
      borutaBeforeTopN: String,
      borutaAfterTopN: String,
      reportHome: ReportHomeData,
      colorSolution: Option[String]
  )

  case class KeggInfoData(finalName: String, accession: String, keggid: String, superclass: String, cleanName: String)

  case class MyConfigTest(value: String) extends MyConfig

  case class FileInfoData(
      fileName: String,
      intro: String,
      tags: String = "other",
      dataFileName: String = "",
      kind: String = "",
      fileRelPath: String = ""
  )

}
